package edu.hit.stu.config;

import edu.hit.stu.pojo.Authorities;
import edu.hit.stu.pojo.Users;
import edu.hit.stu.repository.AuthoritiesRepository;
import edu.hit.stu.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author 刘智彬
 */
@Service
@RequiredArgsConstructor
public class IReactiveUserDetailsServiceImpl implements ReactiveUserDetailsService, ReactiveUserDetailsPasswordService {

    private final UserRepository userRepository;
    private final AuthoritiesRepository authoritiesRepository;
    private final PasswordEncoder passwordEncoder;

    @Override
    public Mono<UserDetails> updatePassword(UserDetails user, String newPassword) {
        return null;
    }

    @Override
    public Mono<UserDetails> findByUsername(String username) {
        Optional<Users> optionalUser = userRepository.findById(username);
        Users user = optionalUser.orElseThrow(() -> {
            throw new IllegalArgumentException("未查到用户名为" + username + "的用户");
        });
        List<Authorities> allByUsername = authoritiesRepository.findAllByUsername(username);
        if (allByUsername.isEmpty()) {
            throw new IllegalArgumentException("未查到用户名为" + username + "的用户的权限！");
        }

        List<SimpleGrantedAuthority> collect = allByUsername.stream()
                .map(Authorities::getAuthority)
                .map(str -> "ROLE_" + str)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

        UserDetails userDetails = User.builder()
                .passwordEncoder(passwordEncoder::encode)
                .username(username)
                .password(user.getPassword())
                .authorities(collect)
                .build();
        return Mono.just(userDetails);
    }
}
